package com.example.synchronizedLearning;

public class Syn4 {
    /**
     * 在 Java 的多线程模型中，存在两种不同的锁：
     * 对象锁（Instance Lock） → 锁住当前对象（this）
     * 类锁（Class Lock） → 锁住类对象（Class）
     * 它们是不同层级的锁，互不干扰，因此：
     * 如果线程 A 持有对象锁，线程 B 仍然可以获取类锁。
     * 如果线程 A 持有类锁，线程 B 仍然可以获取对象锁。
     *
     * 对象锁锁住的是堆（Heap）中的对象实例。
     * 类锁锁住的是方法区（Method Area）中的 Class对象。
     * 它们在 JVM 内部是完全不同的对象，因此互不干扰。
     */
    /**
     * 实例方法-->锁住对象
     */
    public synchronized void printA() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "- printA -" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 静态方法-->锁住类
     */
    public synchronized static void printB() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "- printB -" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

/**
 * 如果一个线程锁住的是对象锁（实例方法上的 synchronized），
 * 另一个线程锁住的是类锁（静态方法上的 synchronized），
 * 这两个锁互不干扰，可以并行执行。
 */
class Syn4Test {
    public static void main(String[] args) {

        Syn4 syn4 = new Syn4();

        /**
         * 锁住对象
         */
        Thread t1 = new Thread(syn4::printA);
        t1.setName("t1");
        Thread t1_1 = new Thread(syn4::printA);
        t1_1.setName("t1_1");

        /**
         * 锁住类
         */
        Thread t2 = new Thread(Syn4::printB);
        t2.setName("t2");
        Thread t2_1 = new Thread(Syn4::printB);
        t2_1.setName("t2_1");

        /**
         * printA() 被 synchronized 修饰，锁住的是对象实例（obj）。
         * printB() 被 synchronized static 修饰，锁住的是类对象（MyClass.class）。
         * 由于对象锁和类锁是不同的，因此两个线程可以同时执行。
         */

        t1.start();
        t2.start();
        t1_1.start();
        t2_1.start();

        /**
         * 类锁 → 锁住 MyClass.class，是唯一的
         * 对象锁 → 锁住对象实例 this，每个实例都有独立的对象锁
         * 对象锁和类锁作用于不同的锁对象，所以互不影响
         */

    }
}
